package IC;

import java.io.*;
import java_cup.runtime.*;
import IC.AST.*;
import IC.Parser.*;

import java.util.LinkedList;

public class Compiler{

	//Class fields
	private static String icFile, libraryPath;
	private static Program root_lib, root_file;
	private static	ICClass lc;
	private static String correctFormat= "Usage: <file.ic> -L<LibPath> -print-ast";

	private static boolean is_Library=false;
	private static boolean print_ast=false;


	//Parsing the arguments and  checking arguments
	public static void parseArgs(String[] args){

		if (args.length == 0) {
			throw new RuntimeException("Error: No input file argument was given\n" );
		}		

		icFile = args[0];

		for (int i =1; i< args.length; i++)
		{
			String arg = args[i];

			// library path
			if (arg.startsWith("-L")) 
			{
				is_Library = true;
				libraryPath = arg.substring(2);
			}

			// print-ast
			else 
				if (arg.equalsIgnoreCase("-print-ast")) 
			{
				print_ast = true;
				
			} 

			else 
			{
				throw new RuntimeException("Error: incorrect format. The format should be: "+ correctFormat);
			}
		}
	}	
	//////////////////////////////////////////////////////////////////////////////

	//Scanning and parsing an IC file and pretty-prints it.
	public static void main(String[] args) 	{

		try {
			parseArgs(args);

			//Parsing the library file 

			if(is_Library){
				try 
				{
					FileReader libraryFile = new FileReader(libraryPath);	
					// Create a new scanner
					Lexer libraryScanner = new Lexer(libraryFile);
					
					LibraryParser libParser = new LibraryParser(libraryScanner);
					LinkedList<ICClass> icl= new LinkedList<ICClass>();
					
					Symbol slc= libParser.parse();	
					lc = (ICClass)(slc.value);
					
					icl.add(lc);
					
					root_lib= new Program(icl);		
					
					System.out.println("Parsed " + libraryPath + " successfully!");					

				} 
				catch (IOException ex) 
				{
					System.out.println("unexpected problem (IOException) with libraly file");
					return;
				}
				
				catch( Exception e)  // may throw LexicalError or SyntaxError
				{
					System.out.println("Error in Library File: " + libraryPath );
					System.out.println(e);
					return;
				}

				//Pretty-print the library file
				if(print_ast && is_Library) {
					PrettyPrinter printer = new PrettyPrinter(libraryPath);  //"libic.sig"
					if (root_lib.getClasses() != null)
					{
						//System.out.println(printer.visit(lc));
						System.out.println(root_lib.accept(printer));
					}
					else 
					{
						System.out.println(" root_file.getClasses() == null ");
					}
				}
			}

			///////////////////////////////////////////////////////////////

			//Parsing the input IC file

			try {
				FileReader ICFile = new FileReader(icFile);
				Lexer scanner = new Lexer(ICFile);
				Parser parser = new Parser(scanner);
				
				root_file = (Program) parser.parse().value;
				System.out.println("\nParsed " + icFile + " successfully!");

			}
			catch (IOException ex)
			{
				System.out.println("unexpected problem (IOException) with input file (IC File) ");
				return;
			}
			catch( Exception e)  // may throw LexicalError or SyntaxError
			{
				System.out.println("Error in IC File: " + icFile );
				System.out.println(e);
				return;
			}
			

			//Pretty-print the ic file
			if( print_ast) {				
				PrettyPrinter printer = new PrettyPrinter(icFile);
				if (root_file.getClasses() != null)
				{
					System.out.println(printer.visit(root_file));
				}
				else 
				{
					System.out.println(" root_file.getClasses() == null ");
				}
			}

		} catch (Exception e) {
			
			System.out.println(e.getMessage());
			return;
		}
	}
}